/*******************************************************************************
 *
 * File:        LEDMAN.c
 * Progetto:    Robottino
 * Ambiente:    PIC32
 * Data:        14/03/2012
 * Autore:      M. Tili
 * Versione:    00.00
 *
 * Descrizione: 
 *   Modulo di controllo dei LED.
 *
 *
 * Modifica:  gg/mm/aaaa  | N.Cognome
 *                        | Descrizione modifica
 *
 */
#include "CONFIG.h"
#include "TYPEDEFS.h"
#include "GLOBVAR.h"
#include "TIMER.h"
#include "LEDMAN.h"



/*___DEFINIZIONE TIPI E VARIABILI PRIVATE_____________________________________*/

typedef struct tcmdstat {
  e_led_cmd_id id;
  e_cmd_state  state;
}t_cmd_stat;

static t_cmd_stat ledCmdStat[LED_ID_MAX] = {
/*               CMD_ID       CMD_STATE   */
/*LED_ID_00*/ {LED_CMD_NONE, CMD_NOT_SET},
/*LED_ID_01*/ {LED_CMD_NONE, CMD_NOT_SET},
/*LED_ID_02*/ {LED_CMD_NONE, CMD_NOT_SET}
};


/*___DEFINIZIONE FUNZIONI PRIVATE_____________________________________________*/

static void LedManUpdtOneLed(e_led_id ledIDX,
                             e_timer_id tmrOnOff,
                             e_timer_id tmrBlink);



/*___FINE DELLE DEFINIZIONI___________________________________________________*/
/*============================================================================*/


/*******************************************************************************
 *
 *  LedManInit
 *  Descrizione: Questa funzione inizializza i dati del modulo LEDMAN ed i timer
 *               associati.
 *
 */
void LedManInit(void)
{
  int idx;
  for(idx=0;idx <LED_ID_MAX;idx++)
  {
    ledCmdStat[idx].id    = LED_CMD_NONE;
    ledCmdStat[idx].state = CMD_NOT_SET;
    }
  TimerResetById(TIMER_LED00_ONOFF);
  TimerResetById(TIMER_LED00_BLINK);
  TimerResetById(TIMER_LED01_ONOFF);
  TimerResetById(TIMER_LED01_BLINK);
  TimerResetById(TIMER_LED02_ONOFF);
  TimerResetById(TIMER_LED02_BLINK);
}


/*******************************************************************************
 *
 *  LedManSetCmd
 *  Descrizione: Questa funzione imposta il comando per il LED se non c'e' gia'
 *               un comando in corso o in attesa di essere applicato.
 *
 */
BOOLEAN LedManSetCmd(e_led_id ledId, e_led_cmd_id cmdId)
{
  BOOLEAN    retValue;

  retValue = FALSE;

  switch (ledId)
  {
    case LED_ID_00:
    case LED_ID_01:
    case LED_ID_02:
      if ((ledCmdStat[ledId].state != CMD_IN_PROGRESS) &&
          (ledCmdStat[ledId].state != CMD_REQUESTED))
      {
        ledCmdStat[ledId].id    = cmdId;
        ledCmdStat[ledId].state = CMD_REQUESTED;
        retValue = TRUE;
      }
      break;
   default:
      /* DEFENSIVE SHUTDOWN */
     break;
  }
  return retValue;
}


/*******************************************************************************
 *
 *  LedManUpdate
 *  Descrizione: Questa funzione schedula l'aggiornamento dello stato dei 
 *               comandi sui LED.
 *
 */
void LedManUpdate(void)
{
  LedManUpdtOneLed(LED_ID_00, TIMER_LED00_ONOFF, TIMER_LED00_ONOFF);
  LedManUpdtOneLed(LED_ID_01, TIMER_LED01_ONOFF, TIMER_LED01_ONOFF);
  LedManUpdtOneLed(LED_ID_02, TIMER_LED02_ONOFF, TIMER_LED02_ONOFF);
}



/*******************************************************************************
 *
 *  LedManUpdtOneLed
 *  Descrizione: Questa funzione, per uno specifico LED, controlla quale comando
 *               e' stato richiesto e lo applica oppure se il comando e' gia'
 *               applicato ne valuta la completa esecuzione.
 *
 */
static void LedManUpdtOneLed(e_led_id ledIDX,
                             e_timer_id tmrOnOff,
                             e_timer_id tmrBlink)
{
  switch (ledCmdStat[ledIDX].state)
  {
    case CMD_REQUESTED:
      if (ledCmdStat[ledIDX].id == LED_CMD_ON)
      {
        ioDataStat.output.ledState[ledIDX]= STATE_HIGH;
        TimerSet(tmrOnOff, 1000, FALSE);
        ledCmdStat[ledIDX].state = CMD_IN_PROGRESS;
      }
      else if (ledCmdStat[ledIDX].id == LED_CMD_OFF)
      {
        ioDataStat.output.ledState[ledIDX] = STATE_LOW;
        TimerSet(tmrOnOff, 1000, FALSE);
        ledCmdStat[ledIDX].state = CMD_IN_PROGRESS;
      }
      else if (ledCmdStat[ledIDX].id == LED_CMD_BLINK)
      {
        /* Attiva il timer per la gestione del comando */
        TimerSet(tmrOnOff,  300, FALSE);
        TimerSet(tmrBlink, 1200, FALSE);
        ioDataStat.output.ledState[ledIDX] = STATE_HIGH;
        ledCmdStat[ledIDX].state = CMD_IN_PROGRESS;
      }
      break;
    case CMD_IN_PROGRESS:
      /* controlla il timer di esecuzione e se e' scaduto
      *  imposta lo stato a CMD_OK 
      */
      if (ledCmdStat[ledIDX].id == LED_CMD_ON)
      {
        if (TimerHasExpired(tmrOnOff) == TRUE)
        {
          TimerResetById(tmrOnOff);
          ledCmdStat[ledIDX].state = CMD_OK;
        }
      }
      else if (ledCmdStat[ledIDX].id == LED_CMD_OFF)
      {
        if (TimerHasExpired(tmrOnOff) == TRUE)
        {
          TimerResetById(tmrOnOff);
          ledCmdStat[ledIDX].state = CMD_OK;
        }
      }
      else if (ledCmdStat[ledIDX].id == LED_CMD_BLINK)
      {
        /* Attiva il timer per la gestione del comando */
        if (TimerHasExpired(tmrBlink) == TRUE)
        {
          TimerResetById(tmrOnOff);
          TimerResetById(tmrBlink);
          ledCmdStat[ledIDX].state = CMD_OK;
        }
        else if ( TimerHasExpired(tmrOnOff) == TRUE)
        {
          /* cambia stato al led */
          ioDataStat.output.ledState[ledIDX] = 
                         (ioDataStat.output.ledState[ledIDX] == STATE_HIGH) ? 
                         STATE_LOW : STATE_HIGH;
          TimerSet(tmrOnOff, 300, FALSE);
        }
      }
      break;
    default:
      /* DO NOTHING */
      break;
  }
}


